home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
mint104s.zoo
/
mint.src
/
dosfile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-08
|
25KB
|
1,136 lines
/*
Copyright 1990,1991,1992 Eric R. Smith.
Copyright 1992 Atari Corporation.
All rights reserved.
*/
/* DOS file handling routines */
#include "mint.h"
extern char temp1[]; /* see filesys.c */
static long do_dup P_((int,int));
static void unselectme P_((PROC *));
/*
* first, some utility routines
*/
FILEPTR *
do_open(name, rwmode, attr, x)
const char *name; /* file name */
int rwmode; /* file access mode */
int attr; /* TOS attributes for created files (if applicable) */
XATTR *x; /* filled in with attributes of opened file */
{
struct tty *tty;
fcookie dir, fc;
long devsp;
FILEPTR *f;
DEVDRV *dev;
long r;
XATTR xattr;
unsigned perm;
int creating;
extern FILESYS proc_filesys;
/* for special BIOS "fake" devices */
extern DEVDRV fakedev;
TRACE(("do_open(%s)", name));
/*
* first step: get a cookie for the directory
*/
r = path2cookie(name, temp1, &dir);
if (r) {
mint_errno = (int)r;
DEBUG(("do_open(%s): error %ld", name, r));
return NULL;
}
/*
* second step: try to locate the file itself
*/
r = relpath2cookie(&dir, temp1, follow_links, &fc, 0);
/*
* file found: this is an error if (O_CREAT|O_EXCL) are set
*/
if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) {
DEBUG(("do_open(%s): file already exists",name));
mint_errno = EACCDN;
release_cookie(&fc);
release_cookie(&dir);
return NULL;
}
/*
* file not found: maybe we should create it
* note that if r != 0, the fc cookie is invalid (so we don't need to
* release it)
*/
if (r == EFILNF && (rwmode & O_CREAT)) {
/* check first for write permission in the directory */
r = (*dir.fs->getxattr)(&dir, &xattr);
if (r == 0) {
if (denyaccess(&xattr, S_IWOTH))
r = EACCDN;
}
if (r) {
DEBUG(("do_open(%s): couldn't get "
"write permission on directory",name));
mint_errno = (int)r;
release_cookie(&dir);
return NULL;
}
r = (*dir.fs->creat)(&dir, temp1,
(S_IFREG|DEFAULT_MODE) & (~curproc->umask), attr, &fc);
if (r) {
DEBUG(("do_open(%s): error %ld while creating file",
name, r));
mint_errno = (int)r;
release_cookie(&dir);
return NULL;
}
creating = 1;
} else if (r) {
DEBUG(("do_open(%s): error %ld while searching for file",
name, r));
mint_errno = (int)r;
release_cookie(&dir);
return NULL;
} else {
creating = 0;
}
/*
* check now for permission to actually access the file
*/
r = (*fc.fs->getxattr)(&fc, &xattr);
if (r) {
DEBUG(("do_open(%s): couldn't get file attributes",name));
mint_errno = (int)r;
release_cookie(&dir);
release_cookie(&fc);
return NULL;
}
/*
* we don't do directories
*/
if ( (xattr.mode & S_IFMT) == S_IFDIR ) {
DEBUG(("do_open(%s): file is a directory",name));
release_cookie(&dir);
release_cookie(&fc);
mint_errno = EFILNF;
return NULL;
}
switch (rwmode & O_RWMODE) {
case O_WRONLY:
perm = S_IWOTH;
break;
case O_RDWR:
perm = S_IROTH|S_IWOTH;
break;
case O_EXEC:
perm = (fc.fs->fsflags & FS_NOXBIT) ? S_IROTH : S_IXOTH;
break;
case O_RDONLY:
perm = S_IROTH;
break;
default:
perm = 0;
ALERT("do_open: bad file access mode: %x", rwmode);
}
if (!creating && denyaccess(&xattr, perm)) {
DEBUG(("do_open(%s): access to file denied",name));
release_cookie(&dir);
release_cookie(&fc);
mint_errno = EACCDN;
return NULL;
}
/*
* an extra check for write access -- even the superuser shouldn't
* write to files with the FA_RDONLY attribute bit set (unless,
* we just created the file, or unless the file is on the proc
* file system and hence FA_RDONLY has a different meaning)
*/
if ( !creating && (xattr.attr & FA_RDONLY) && fc.fs != &proc_filesys) {
if ( (rwmode & O_RWMODE) == O_RDWR ||
(rwmode & O_RWMODE) == O_WRONLY ) {
DEBUG(("do_open(%s): can't write a read-only file",
name));
release_cookie(&dir);
release_cookie(&fc);
mint_errno = EACCDN;
return NULL;
}
}
/*
* if writing to a setuid or setgid file, clear those bits
*/
if ( (perm & S_IWOTH) && (xattr.mode & (S_ISUID|S_ISGID)) ) {
xattr.mode &= ~(S_ISUID|S_ISGID);
(*fc.fs->chmode)(&fc, (xattr.mode & ~S_IFMT));
}
/*
* If the caller asked for the attributes of the opened file, copy them over.
*/
if (x) *x = xattr;
/*
* So far, so good. Let's get the device driver now, and try to
* actually open the file.
*/
dev = (*fc.fs->getdev)(&fc, &devsp);
if (!dev) {
mint_errno = (int)devsp;
DEBUG(("do_open(%s): device driver not found",name));
release_cookie(&dir);
release_cookie(&fc);
return NULL;
}
if (dev == &fakedev) { /* fake BIOS devices */
f = curproc->handle[devsp];
if (!f) {
mint_errno = EIHNDL;
return 0;
}
f->links++;
release_cookie(&dir);
release_cookie(&fc);
return f;
}
if (0 == (f = new_fileptr())) {
release_cookie(&dir);
release_cookie(&fc);
mint_errno = ENSMEM;
return NULL;
}
f->links = 1;
f->flags = rwmode;
f->pos = 0;
f->devinfo = devsp;
f->fc = fc;
f->dev = dev;
release_cookie(&dir);
r = (*dev->open)(f);
if (r < 0) {
DEBUG(("do_open(%s): device open failed with error %ld",
name, r));
mint_errno = (int)r;
f->links = 0;
release_cookie(&fc);
dispose_fileptr(f);
return NULL;
}
/* special code for opening a tty */
if (is_terminal(f)) {
extern struct tty default_tty; /* in tty.c */
tty = (struct tty *)f->devinfo;
if (tty->use_cnt == 0) { /* first open for this device? */
*tty = default_tty;
}
tty->use_cnt++;
}
return f;
}
/*
* helper function for do_close: this closes the indicated file pointer which
* is assumed to be associated with process p. The extra parameter is necessary
* because f_midipipe mucks with file pointers of other processes, so
* sometimes p != curproc.
*
* Note that the function changedrv() in filesys.c can call this routine.
* in that case, f->dev will be 0 to represent an invalid device, and
* we cannot call the device close routine.
*/
long
do_pclose(p, f)
PROC *p;
FILEPTR *f;
{
long r = 0;
if (!f) return EIHNDL;
/* if this file is "select'd" by this process, unselect it
* (this is just in case we were killed by a signal)
*/
/* BUG? Feature? If media change is detected while we're doing the select,
* we'll never unselect (since f->dev is set to NULL by changedrv())
*/
if (f->dev) {
(*f->dev->unselect)(f, (long)p, O_RDONLY);
(*f->dev->unselect)(f, (long)p, O_WRONLY);
}
f->links--;
/* TTY manipulation must be done *before* calling the device close routine,
* since afterwards the TTY structure may no longer exist
*/
if (is_terminal(f) && f->links <= 0) {
struct tty *tty = (struct tty *)f->devinfo;
tty->use_cnt--;
if (tty->use_cnt <= 0)
tty->pgrp = 0;
if (tty->use_cnt <= 0 && tty->xkey) {
kfree(tty->xkey);
tty->xkey = 0;
}
}
if (f->dev) {
r = (*f->dev->close)(f, p->pid);
if (r) {
DEBUG(("close: device close failed"));
}
}
if (f->links <= 0) {
release_cookie(&f->fc);
dispose_fileptr(f);
}
return r;
}
long
do_close(f)
FILEPTR *f;
{
return do_pclose(curproc, f);
}
long ARGS_ON_STACK
f_open(name, mode)
const char *name;
int mode;
{
int i;
FILEPTR *f;
PROC *proc;
TRACE(("Fopen(%s, %x)", name, mode));
#if O_GLOBAL
if (mode & O_GLOBAL) {
/* oh, boy! user wants us to open a global handle! */
proc = rootproc;
}
else
#endif
proc = curproc;
for (i = MIN_OPEN; i < MAX_OPEN; i++) {
if (!proc->handle[i])
goto found_for_open;
}
DEBUG(("Fopen(%s): process out of handles",name));
return ENHNDL; /* no more handles */
found_for_open:
mode &= O_USER; /* make sure the mode is legal */
/* note: file mode 3 is reserved for the kernel; for users, transmogrify it
* into O_RDWR (mode 2)
*/
if ( (mode & O_RWMODE) == O_EXEC ) {
mode = (mode & ~O_RWMODE) | O_RDWR;
}
f = do_open(name, mode, 0, (XATTR *)0);
if (!f) {
return m